#include "i2c_hard.h"
#include "gd32f4xx.h"
#include "systick.h"

// 超时次数
static int TIMEOUT = 50000;

void i2c_hard_init() {
    // SCL	PB6
    rcu_periph_clock_enable(I2C_SCL_RCU);
    gpio_mode_set(I2C_SCL_PORT, GPIO_MODE_AF, GPIO_PUPD_NONE, I2C_SCL_PIN);
    gpio_output_options_set(GPIOB, GPIO_OTYPE_OD, GPIO_OSPEED_MAX, I2C_SCL_PIN);
    gpio_af_set(I2C_SCL_PORT, I2C_SCL_AF, I2C_SCL_PIN);

    // SDA	PB7
    rcu_periph_clock_enable(I2C_SDA_RCU);
    gpio_mode_set(I2C_SDA_PORT, GPIO_MODE_AF, GPIO_PUPD_NONE, I2C_SDA_PIN);
    gpio_output_options_set(I2C_SDA_PORT, GPIO_OTYPE_OD, GPIO_OSPEED_MAX, I2C_SDA_PIN);
    gpio_af_set(I2C_SDA_PORT, I2C_SDA_AF, I2C_SDA_PIN);

    //////////// I2C电路
    rcu_periph_clock_enable(I2C_RCU);
    i2c_deinit(I2C_X);
    // I2C速率配置
    i2c_clock_config(I2C_X, I2C_SPEED, I2C_DTCY_2);

    // 使能i2c 0000 000r/w
    i2c_mode_addr_config(I2C_X, I2C_I2CMODE_ENABLE, I2C_ADDFORMAT_7BITS, 0x00);
    i2c_enable(I2C_X);
    i2c_ack_config(I2C_X, I2C_ACK_ENABLE);
}
static uint8_t I2C_wait(uint32_t flag) {
    uint16_t cnt = 0;

    while (!i2c_flag_get(I2C_X, flag)) {
        cnt++;
        if (cnt > TIMEOUT) return 1;
    }
    return 0;
}

static uint8_t I2C_waitn(uint32_t flag) {
    uint16_t cnt = 0;

    while (i2c_flag_get(I2C_X, flag)) {
        cnt++;
        if (cnt > TIMEOUT) return 1;
    }
    return 0;
}

/**
 * @desc  : I2C 写数据
 * @date  : 2024-11-20
 * @author: AnRui
 * @param :  addr -{设备地址 7位}:
 * @param :  reg  -{寄存器地址}:
 * @param :  data -{保存数据的数组的指针}:
 * @param :  len  -{数组长度}:
 * @return: 0:正常  1 代表发送设备地址错误  2 代表发送寄存器地址错误 3 代表发送数据错误
 */
uint8_t i2c_hard_write(uint8_t addr, uint8_t reg, uint8_t* data, uint32_t len) {
    // addr设备地址， 0000 000(r/w)
    uint8_t waddr = addr << 1;

    /************* start ***********************/
    // 等待I2C 总线闲置 1:busy 0:free 
    if (I2C_waitn(I2C_FLAG_I2CBSY)) return 1;
    // start
    i2c_start_on_bus(I2C_X);
    // 等待I2C主设备成功发送起始信号 1 发送完成 0 待发送 
    if (I2C_wait(I2C_FLAG_SBSEND)) return 2;

    /************* device address **************/
    // 发送设备地址(写地址)
    i2c_master_addressing(I2C_X, waddr, I2C_TRANSMITTER);
    // 等待地址发送完成
    if (I2C_wait(I2C_FLAG_ADDSEND)) return 3;
    i2c_flag_clear(I2C_X, I2C_FLAG_ADDSEND);


    /************ register address ************/
     // 寄存器地址
     // 等待发送数据缓冲区为空
    if (I2C_wait(I2C_FLAG_TBE)) return 4;
    // 发送数据
    i2c_data_transmit(I2C_X, reg);
    // 等待数据发送完成
    if (I2C_wait(I2C_FLAG_BTC)) return 5;

    /***************** data ******************/
      // 发送数据
    uint32_t i;
    for (i = 0; i < len; i++) {
        uint32_t d = data [i];

        // 等待发送数据缓冲区为空
        if (I2C_wait(I2C_FLAG_TBE)) return 6;

        // 发送数据
        i2c_data_transmit(I2C_X, d);

        // 等待数据发送完成
        if (I2C_wait(I2C_FLAG_BTC)) return 7;
    }
    /***************** stop ********************/
    // stop
    i2c_stop_on_bus(I2C_X);

    return I2C_RESULT_OK;// 成功

}

/**
 * @desc  : 读数据
 * @date  : 2024-11-19
 * @author: AnRui
 * @param :  addr -{设备地址 7位}:
 * @param :  reg  -{寄存器地址}:
 * @param :  data -{保存数据的数组的指针}:
 * @param :  len  -{数组长度}:
 * @return: 0:正常  1 代表发送设备地址错误  2 代表发送寄存器地址错误 3 代表发送数据错误
 */
uint8_t i2c_hard_read(uint8_t addr, uint8_t reg, uint8_t* data, uint32_t len) {

    uint8_t waddr = addr << 1;
    uint8_t raddr = (addr << 1) | 1;

    // 开始
    /************* start ***********************/
    // 等待I2C空闲
    if (I2C_waitn(I2C_FLAG_I2CBSY)) return 1;

    // 发送启动信号
    i2c_start_on_bus(I2C_X);
    if (I2C_wait(I2C_FLAG_SBSEND)) return 2;


    // 发送设备地址(写地址)
    /************* device address **************/
    // 发送从设备地址
    i2c_master_addressing(I2C_X, waddr, I2C_TRANSMITTER);

    if (I2C_wait(I2C_FLAG_ADDSEND)) return 3;
    i2c_flag_clear(I2C_X, I2C_FLAG_ADDSEND);


    // 发送寄存器地址
    /********** register address **************/
    // 等待发送缓冲区
    if (I2C_wait(I2C_FLAG_TBE)) return 4;
    // 发送寄存器地址
    i2c_data_transmit(I2C_X, reg);
    // 等待发送数据完成
    if (I2C_wait(I2C_FLAG_BTC)) return 5;

    /************* start ***********************/
    // 发送再启动信号
    i2c_start_on_bus(I2C_X);
    if (I2C_wait(I2C_FLAG_SBSEND)) return 7;

    /************* device address **************/
    // 发送从设备地址
    i2c_master_addressing(I2C_X, raddr, I2C_RECEIVER);
    if (I2C_wait(I2C_FLAG_ADDSEND)) return 8;
    i2c_flag_clear(I2C_X, I2C_FLAG_ADDSEND);
    /************* data **************/
    //收到数据后 自动发送 ack
    i2c_ack_config(I2C_X, I2C_ACK_ENABLE);// send ack
    i2c_ackpos_config(I2C_X, I2C_ACKPOS_CURRENT);// 接收一个数据之后，就自动发送ack
    if (I2C_wait((I2C_CTL0(I2C_X) & I2C_CTL0_ACKEN))) return 11;

    // 读取数据
    uint8_t i;
    for (i = 0; i < len; i++) {

        // 等待ACK数据发送完成
        // 等待接收缓冲区
        if (I2C_wait(I2C_FLAG_RBNE)) return 10;
        data [i] = i2c_data_receive(I2C_X);

        if (i == len - 2) {
            // 在读取最后一个字节之前，禁用ACK，并发送停止信号  这样才会在收到最后一个数据的时候 发送nack
            // 配置自动NACK
            i2c_ack_config(I2C_X, I2C_ACK_DISABLE);
            if (I2C_wait((I2C_CTL0(I2C_X) & I2C_CTL0_ACKEN))) return 12;
        }
    }
    /***************** stop ********************/
    i2c_stop_on_bus(I2C_X);

    return 0;

}



